package com.cmwa.solution.utils.cached;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import com.cmwa.solution.exception.CachedException;
import com.cmwa.solution.exception.ValidateFailedException;
import com.cmwa.solution.sys.dictionary.entity.DictionaryVo;
import com.cmwa.solution.sys.dictionary.service.DictionaryService;
import com.cmwa.solution.utils.cached.service.ShareCachedService;

/**
 * 字典缓存类
 * 
 * @author pangtf
 */
@Component
public class DictionaryCached implements ShareCachedService, InitializingBean {
	@Resource
	private DictionaryService dictionaryService;

	private static Map<DictEntry, String> dictCached = new HashMap<DictEntry, String>(1024);
	
	/**
	 * 数据字典缓存集合
	 */
	private static List<DictionaryVo> dictionaryVos = new Vector<DictionaryVo>();
	
	private static DictionaryCached instance;

	public static DictionaryCached getInstance(){
		if(instance == null){
			instance = new DictionaryCached();
		}
		
		return instance;
	}
	
	
	@Override
	public void afterPropertiesSet() throws Exception {
		loadMappingCached();
	}

	/**
	 * dictCached要已删除，dictionaryVos不要已删除
	 */
	@Override
	public void loadMappingCached() throws CachedException {
		dictCached.clear();
		DictionaryVo dctDto = new DictionaryVo();
	    dictionaryVos = dictionaryService.listDictionary(dctDto);
		for (DictionaryVo dictionaryVo : dictionaryVos) {
			DictEntry entry = new DictEntry();
			entry.setDctRootType(dictionaryVo.getDctRootType());
			entry.setDctFathType(dictionaryVo.getDctFathType());
			entry.setDctLeftType(dictionaryVo.getDctLeftType());
			entry.setDctValue(dictionaryVo.getDctValue());
			dictCached.put(entry, dictionaryVo.getDctName());
		}
		
		Iterator<DictionaryVo> iterator = dictionaryVos.iterator();
		while(iterator.hasNext()){
			DictionaryVo dictionaryVo = iterator.next();
			if("D".equals(dictionaryVo.getStat())){
				iterator.remove();
		    }
		}
	}

	/**
	 * 代替存储过程中的 IBF_GET_DCTNAME_EX()函数
	 * 
	 * @param dctType
	 *            --根类型
	 * @param dctValue
	 *            --字典值
	 * @return
	 */
	public static String getDictName(String dctType, String dctValue) {
		return getDictName(dctType, dctType, dctType, dctValue);
	}
	
	/**
	 * 多个字典值取值(例如：字典值dctValue=1,2需取值=张三,李四)
	 * @param dctType	字典类型
	 * @param dctValue	字典值
	 * @param splitType	多个值的分符
	 * @return
	 */
	public static String getDictNameByArry(String dctType, String dctValue,String splitType) {
		StringBuffer dctNameArry = new StringBuffer();
		if (dctValue != null) {
			String[] dctArry = dctValue.split(splitType);
			for (int i = 0; i < dctArry.length; i++) {
				String dict = dctArry[i];
				dctNameArry.append(getDictName(dctType, dict));
				if (i < dctArry.length - 1) 
					dctNameArry.append(splitType);
			}
		}
		return dctNameArry.toString();
	}
	
	/**
	 * 多个字典值取值(例如：字典值dctValue=1,2需取值=张三,李四)
	 * @param dctType	字典类型
	 * @param dctValue	字典值
	 * @param splitType	多个值的分符
	 * @return、DCTROOTTYPE、DCTFATHTYPE、DCTLEFTTYPE三种类型不一样   INVEST_PATH_TYPE
	 */
	public static String getDictNameByArrys(String dctType, String dctValue,String splitType) {
		StringBuffer dctNameArry = new StringBuffer();
		if (dctValue != null) {
			String[] dctArry = dctValue.split(splitType);
			for (int i = 0; i < dctArry.length; i++) {
				String dict = dctArry[i];
				String subdict = dict.substring(0, 1);
				String dctFathType = dctType+"_"+subdict;
				String dctLeftType = dctType+"_"+dict;
				if(dict.length()>1){
					dctNameArry.append(getDictName(dctType, dctFathType, dctLeftType, dict));
				}else{
					dctNameArry.append(getDictName(dctType, dctType, dctLeftType, dict));
				}
				
				if (i < dctArry.length - 1) 
					dctNameArry.append(splitType);
			}
		}
		return dctNameArry.toString();
	}

	/**
	 * 代替存储过程中的 IBF_GET_DCTNAME_EX()函数
	 * @param dctType 字典根类型,父类型
	 * @param dctLeftType 字典子类型
	 * @param dctValue 字典值
	 * @return
	 */
	public static String getDictName(String dctType, String dctLeftType, String dctValue) {
		return getDictName(dctType, dctType, dctLeftType, dctValue);
	}

	public static String getDictName(String dctRootType, String dctFathType, String dctLeftType, String dctValue) {
		DictEntry entry = new DictEntry(dctRootType, dctFathType, dctLeftType, dctValue);
		return dictCached.get(entry);
	}
	
	/**
	 * 代替存储过程中的 e：IBF_GET_DCTNAME('CAH_BIZ_TYP','CAH_BIZ_TYP','', TPCF.BNSTYPE)函数<br>
	 * 用于子类型不确定的情况
	 * @param dctRootType 字典根类型
	 * @param dctFathType 字典父类型
	 * @param dctValue  字典值
	 * @return
	 */
	public static String getDictNameNoLeftPath(String dctRootType, String dctFathType, String dctValue) {
		for (DictEntry entry:dictCached.keySet()) {
			if (entry.dctRootType.equals(dctRootType) && entry.dctFathType.equals(dctFathType) && entry.dctValue.equals(dctValue)) {
				return dictCached.get(entry);
			}
		}
		return "";
	}
	
	/**
	 * 根据字典根类型及字典名获取字典值
	 * @author ex-hejm
	 * @date 2018年10月30日 下午1:33:17
	 * @param dctRootType
	 * @param dctName
	 * @return
	 */
	public static String getDictValueByTypeAndName(String dctRootType, String dctName) {
		if (dictionaryVos == null || StringUtils.isBlank(dctName) || StringUtils.isBlank(dctRootType)) {
			return "";
		} else {
			for (int i = 0; i < dictionaryVos.size(); i++) {
				DictionaryVo dto = (DictionaryVo) dictionaryVos.get(i);
				if (dctRootType.equals(dto.getDctRootType())
						&& dctRootType.equals(dto.getDctFathType())
						&& dctRootType.equals(dto.getDctLeftType())
						&& dctName.equals(dto.getDctName())) {
					return dto.getDctValue();
				}
			}
			return "";
		}
	}
	
	public static String getDictNameByRootType(String dctRootType, String dctValue) {
		for (DictEntry entry:dictCached.keySet()) {
			if (entry.dctRootType.equals(dctRootType) && entry.dctValue.equals(dctValue)) {
				return dictCached.get(entry);
			}
		}
		return "";
	}

	public static String getDictNameNoFathType(String dctRootType, String dctValue) {
		for (DictEntry entry:dictCached.keySet()) {
			if (entry.dctRootType.equals(dctRootType) && entry.dctValue.equals(dctValue)) {
				return dictCached.get(entry);
			}
		}
		return "";
	}
	
	public static DictEntry getDictNoFathType(String dctRootType, String dctValue) {
		for (DictEntry entry:dictCached.keySet()) {
			if (entry.dctRootType.equals(dctRootType) && entry.dctValue.equals(dctValue)) {
				return entry;
			}
		}
		return null;
	}
	
	
	/**
	 * 获取单个数据字典
	 * 
	 * @param dctId
	 *            String 数据字典代码
	 * @return DictionaryVo
	 */
	public DictionaryVo getDictionary(String dctId) {
		if (dictionaryVos == null) {
			return null;
		}
		if (dictionaryVos != null && dictionaryVos.size() > 0) {
			for (int i = 0; i < dictionaryVos.size(); i++) {
				DictionaryVo dtoTmp = (DictionaryVo) dictionaryVos.get(i);
				if (dtoTmp != null) {
					if (dctId.equals(dtoTmp.getDctId())) {
						return dtoTmp;
					}
				}
			}
		}
		return null;
	}

	/**
	 * 根据数据字典代码获取数据字典名称
	 * 
	 * @param dctId
	 *            String 数据字典代码
	 * @return String
	 */
	public String getDictionaryName(String dctId) {

		DictionaryVo dto = getDictionary(dctId);
		if (dto != null) {
			return dto.getDctName();
		} else {
			return "";
		}
	}

	/**
	 * 根据数据字典类型和字典值获取数据字典名称
	 * 
	 * @param dctType
	 *            String 数据字典类型
	 * @param dctType
	 *            String 数据字典值
	 * @return String
	 */
	public String getDictionaryName(String dctRootType, String dctFathType,
			String dctLeftType, String dctValue) {

		if (dictionaryVos == null) {
			return "";
		} else {
			for (int i = 0; i < dictionaryVos.size(); i++) {
				DictionaryVo dto = (DictionaryVo) dictionaryVos.get(i);
				if (dctRootType.equals(dto.getDctRootType())
						&& dctFathType.equals(dto.getDctFathType())
						&& dctLeftType.equals(dto.getDctLeftType())
						&& dctValue.equals(dto.getDctValue())) {

					return dto.getDctName();
				}
			}
			return "";
		}
	}
	
	/**
	 * 根据数据字典类型和字典名称获取数据字典值
	 */
	public String getDictionaryValue(String dctRootType, String dctFathType,
			String dctLeftType, String dctName) {

		if (dictionaryVos == null) {
			return "";
		} else {
			for (int i = 0; i < dictionaryVos.size(); i++) {
				DictionaryVo dto = (DictionaryVo) dictionaryVos.get(i);
				if (dctRootType.equals(dto.getDctRootType())
						&& dctFathType.equals(dto.getDctFathType())
						&& dctLeftType.equals(dto.getDctLeftType())
						&& dctName.equals(dto.getDctName())) {

					return dto.getDctValue();
				}
			}
			return "";
		}
	}

	public String getDictionrySelHtml(String dctRootType, String dctFathType,
			String dctLeftType, String selName, String onChange, String defalt) {
		if (dictionaryVos == null) {
			return "<select name='" + selName + "' onChange='" + onChange
					+ "' class='form-text'><option value=''></option></select>";
		} else {
			String selHtml = "<select name='" + selName + "' id='" + selName + "' onChange='"
					+ onChange + "' class='form-text'>";
			for (int i = 0; i < dictionaryVos.size(); i++) {
				DictionaryVo dto = (DictionaryVo) dictionaryVos.get(i);
				if (dctRootType.equals(dto.getDctRootType())
						&& dctFathType.equals(dto.getDctFathType())
						&& dctLeftType.equals(dto.getDctLeftType())) {

					String selected = "";
					if (defalt != null && defalt.equals(dto.getDctValue())) {
						selected = "selected";
					}

					selHtml += "<option value='" + dto.getDctValue() + "' "
							+ selected + ">";
					selHtml += dto.getDctName();
					selHtml += "</option>";
				}
			}
			selHtml += "</select>";

			return selHtml;
		}
	}

	public String getDictionryAllSelHtml(String dctRootType, String dctFathType,
			String dctLeftType, String selName, String onChange, String defalt) {
		if (dictionaryVos == null) {
			return "<select name='" + selName + "' onChange='" + onChange
					+ "' class='form-text'><option value=''></option></select>";
		} else {
			String selHtml = "<select name='" + selName + "' id='" + selName + "' onChange='"
					+ onChange + "' class='form-text'>";
			selHtml += "<option value=''>全部</option>";
			for (int i = 0; i < dictionaryVos.size(); i++) {
				DictionaryVo dto = (DictionaryVo) dictionaryVos.get(i);
				if (dctRootType.equals(dto.getDctRootType())
						&& dctFathType.equals(dto.getDctFathType())
						&& dctLeftType.equals(dto.getDctLeftType())) {

					String selected = "";
					if (defalt != null && defalt.equals(dto.getDctValue())) {
						selected = "selected";
					}

					selHtml += "<option value='" + dto.getDctValue() + "' "
							+ selected + ">";
					selHtml += dto.getDctName();
					selHtml += "</option>";
				}
			}
			selHtml += "</select>";

			return selHtml;
		}
	}

	/**
	 * 根据数据字典类型和是否叶子节点字段
	 * 
	 * @param dctType
	 *            String 数据字典类型
	 * @param isLeaf
	 *            String 是否叶子节点
	 * @return String
	 */
	public static List<DictionaryVo> getDictionaryByType(String dctType) {
		return getDictionaryByType(dctType, dctType, dctType);
	}	
	
	/**
	 * 根据数据字典类型获取列表，不含数据项目说明
	 * 
	 * @param dctRootType
	 *            String 数据字典根类型
	 * @param dctFathType
	 * 			  String 数据字典父类型
	 * @param dctLeftType
	 * 			  String 数据字典子类型
	 * @return List 返回该类型的列表
	 */
	public static List<DictionaryVo> getDictionaryByType(String dctRootType, String dctFathType, String dctLeftType) {
		List<DictionaryVo> vList = new Vector<DictionaryVo>();
		if ((dictionaryVos == null || dictionaryVos.size() == 0)) {
			return vList;
		} else {
			for (int i = 0; i < dictionaryVos.size(); i++) {
				DictionaryVo dto = (DictionaryVo) dictionaryVos.get(i);
				if (dctRootType.equals(dto.getDctRootType())
						&& dctFathType.equals(dto.getDctFathType())
						&& dctLeftType.equals(dto.getDctLeftType())
						&& !dctRootType.equals(dto.getDctValue())
					) {
					vList.add(dto);
				}
			}
			return vList;
		}
	}
	
	/**
	 * 根据rootType获取
	 * @param dctRootType
	 * @return
	 */
	public static List<DictionaryVo> getDictionaryByRootType(String dctRootType) {
		List<DictionaryVo> vList = new Vector<DictionaryVo>();
		if ((dictionaryVos == null || dictionaryVos.size() == 0)) {
			return vList;
		} else {
			for (int i = 0; i < dictionaryVos.size(); i++) {
				DictionaryVo dto = (DictionaryVo) dictionaryVos.get(i);
				if (dctRootType.equals(dto.getDctRootType())
						&&!dctRootType.equals(dto.getDctValue())) {
					vList.add(dto);
				}
			}
			return vList;
		}
	}
	
	/**
	 * 根据数据字典类型获取列表，不含数据项目说明
	 * 
	 * @param dctRootType
	 *            String 数据字典根类型
	 * @param dctFathType
	 * 			  String 数据字典父类型
	 * @return List 返回该类型的列表
	 */
	public static List<DictionaryVo> getDictionaryByType(String dctRootType, String dctFathType) {
		List<DictionaryVo> vList = new Vector<DictionaryVo>();
		if ((dictionaryVos == null || dictionaryVos.size() == 0)) {
			return vList;
		} else {
			for (int i = 0; i < dictionaryVos.size(); i++) {
				DictionaryVo dto = (DictionaryVo) dictionaryVos.get(i);
				if (dctRootType.equals(dto.getDctRootType())
						&& dctFathType.equals(dto.getDctFathType())
						&& !dctRootType.equals(dto.getDctValue())
					) {
					vList.add(dto);
				}
			}
			return vList;
		}
	}

	public List<DictionaryVo> getDictionaryByTypeAndValue(String dctType, String dctValue)
	{
		return getDictionaryByTypeAndValue(dctType, dctType, dctType, dctValue);
	}
	
	/**
	 * 
	 * @param dctRootType
	 * @param dctFathType
	 * @param dctLeftType
	 * @param dctValue
	 * @return
	 */
	public List<DictionaryVo> getDictionaryByTypeAndValue(String dctRootType, String dctFathType, 
			String dctLeftType, String dctValue) {
		List<DictionaryVo> vList = new Vector<DictionaryVo>();
		if ((dictionaryVos == null || dictionaryVos.size() == 0)) {
			return vList;
		} else {
			for (int i = 0; i < dictionaryVos.size(); i++) {
				DictionaryVo dto = (DictionaryVo) dictionaryVos.get(i);
				if (dctRootType.equals(dto.getDctRootType())
						&& dctFathType.equals(dto.getDctFathType())
						&& dctLeftType.equals(dto.getDctLeftType())
						&& dctValue.equals(dto.getDctValue())
					) {
					vList.add(dto);
				}
			}
			return vList;
		}
	}

	public DictionaryService getDictionaryService() {
		return dictionaryService;
	}

	public void setDictionaryService(DictionaryService dictionaryService) {
		this.dictionaryService = dictionaryService;
	}
	/**
	 * 批量添加或修改
	 * @author ex-dingxq 2016-6-15
	 * @param dictList
	 * @throws ValidateFailedException 
	 */
	public void insertOrUpdateDict(List<DictionaryVo> dictList)throws ValidateFailedException {
		List<DictionaryVo> insetDictList = new ArrayList<DictionaryVo>();
		List<DictionaryVo> updateDictList = new ArrayList<DictionaryVo>();
		if (dictList != null) {
			for (int i = 0; i < dictList.size(); i++) {
				DictionaryVo dictDto = dictList.get(i);
				if (dictDto != null) {
					List<DictionaryVo> tempList = getDictionaryByTypeAndValue(dictDto.getDctRootType(), dictDto.getDctFathType(),
							dictDto.getDctLeftType(), dictDto.getDctValue());
					
					// 判断是否需要新增、修改
					if (tempList != null && tempList.size() > 0) {
						DictionaryVo dictDtotmp = (DictionaryVo) tempList.get(0);
						if (dictDtotmp != null && !dictDto.getDctName().equals(dictDtotmp.getDctName())) {
							dictDto.setDctId(dictDtotmp.getDctId());
							updateDictList.add(dictDto);
						}
					} else {
						insetDictList.add(dictDto);
					}
				}
			}

			// 批量新增(后期修改成存储过程批量新增)
			for (int i = 0; i < insetDictList.size(); i++) {
				DictionaryVo dictDto = (DictionaryVo) insetDictList.get(i);
				dictionaryService.saveDictionary(dictDto);
			}

			// 批量修改(后期修改成存储过程批量新增)
			for (int i = 0; i < updateDictList.size(); i++) {
				DictionaryVo dictDto = (DictionaryVo) updateDictList.get(i);
				dictionaryService.updateDictionary(dictDto);
			}

			// 刷新缓存
			reload();
		}
	}
	
	/**
	 * 刷新缓存
	 */
	public void reload() {
		try {
			loadMappingCached();
		} catch (CachedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 字典内部类
	 */
	public static class DictEntry {
		private String dctRootType; // 字典根类型
		private String dctFathType; // 字典父类型
		private String dctLeftType; // 字典子类型
		private String dctValue; // 字典值

		public DictEntry() {
		}

		public DictEntry(String dctRootType, String dctFathType, String dctLeftType, String dctValue) {
			super();
			this.dctRootType = dctRootType;
			this.dctFathType = dctFathType;
			this.dctLeftType = dctLeftType;
			this.dctValue = dctValue;
		}

		public String getDctRootType() {
			return dctRootType;
		}

		public void setDctRootType(String dctRootType) {
			this.dctRootType = dctRootType;
		}

		public String getDctFathType() {
			return dctFathType;
		}

		public void setDctFathType(String dctFathType) {
			this.dctFathType = dctFathType;
		}

		public String getDctLeftType() {
			return dctLeftType;
		}

		public void setDctLeftType(String dctLeftType) {
			this.dctLeftType = dctLeftType;
		}

		public String getDctValue() {
			return dctValue;
		}

		public void setDctValue(String dctValue) {
			this.dctValue = dctValue;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((dctFathType == null) ? 0 : dctFathType.hashCode());
			result = prime * result + ((dctLeftType == null) ? 0 : dctLeftType.hashCode());
			result = prime * result + ((dctRootType == null) ? 0 : dctRootType.hashCode());
			result = prime * result + ((dctValue == null) ? 0 : dctValue.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			DictEntry other = (DictEntry) obj;
			if (dctFathType == null) {
				if (other.dctFathType != null)
					return false;
			} else if (!dctFathType.equals(other.dctFathType))
				return false;
			if (dctLeftType == null) {
				if (other.dctLeftType != null)
					return false;
			} else if (!dctLeftType.equals(other.dctLeftType))
				return false;
			if (dctRootType == null) {
				if (other.dctRootType != null)
					return false;
			} else if (!dctRootType.equals(other.dctRootType))
				return false;
			if (dctValue == null) {
				if (other.dctValue != null)
					return false;
			} else if (!dctValue.equals(other.dctValue))
				return false;
			return true;
		}
	}

}